package cn.CommonUtils;

import cn.Dao.ApplicationConfigurationDao;
import cn.Entity.ApplicationConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;

import java.util.Hashtable;
import java.util.List;
import java.util.Map;

/**
 * 应用程序（项目）需要使用的配置单例工厂类
 * add by 2019年12月8日 星期日
 */
@Slf4j
@Component
public class ApplicationConfigurationSingletonFactory {

//  配置DAO对象
    @Autowired
    private static ApplicationConfigurationDao applicationConfigurationDao;

//    配置集合（表）
    private volatile static Hashtable hashtable = null;

//    最后一次载入配置时间
    private volatile static Long lastLoadApplicationConfigurationTime ;

    private volatile static ApplicationPropertiesUtils applicationPropertiesUtils = new ApplicationPropertiesUtils();

//    重载应用配置间隔时间
    private volatile static Long ReloadApplicationConfigurationIntervalTime = 0L;

//    单例模式，将构造函数私有化
    private ApplicationConfigurationSingletonFactory() {


    }

//    静态代码块
    static {
        lastLoadApplicationConfigurationTime = 0L;
        ReloadApplicationConfigurationIntervalTime = applicationPropertiesUtils.getPropertyByLong("ReloadApplicationConfigurationIntervalTime");
    }

//    获取配置集合实例
    public synchronized static Map getInstance(){

        if (lastLoadApplicationConfigurationTime + ReloadApplicationConfigurationIntervalTime*1000 > System.currentTimeMillis()) {
            log.warn("调用载入applicationConfiguration配置过于频繁，已超过设置间隔时间："+ReloadApplicationConfigurationIntervalTime + "currentTimeMillis："+System.currentTimeMillis());
            throw new RuntimeException("调用载入applicationConfiguration配置过于频繁");
        }

        if (hashtable != null) {
            lastLoadApplicationConfigurationTime = System.currentTimeMillis();
            return hashtable;
        }else{
            if (applicationConfigurationDao != null) {
                List<ApplicationConfiguration> applicationConfigurationList = applicationConfigurationDao.selectList(null);
                hashtable = new Hashtable();
                applicationConfigurationList.forEach(i->{
                    hashtable.put(i.getKeyAC(), i.getValueAC());
                });
            }else{
                WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
                Object obj = wac.getBean(ApplicationConfigurationDao.class);
                if (obj != null) {
                    applicationConfigurationDao = (ApplicationConfigurationDao) obj;
                    List<ApplicationConfiguration> applicationConfigurationList = applicationConfigurationDao.selectList(null);
                    hashtable = new Hashtable();
                    applicationConfigurationList.forEach(i->{
                        hashtable.put(i.getKeyAC(), i.getValueAC());
                    });

                }else{
                    throw new RuntimeException("初始化异常：没有拿到实例化的applicationConfigurationDao对象" + ApplicationConfigurationSingletonFactory.class.getCanonicalName());
                }

            }
        }
        lastLoadApplicationConfigurationTime = System.currentTimeMillis();
        return hashtable;
    }

//    重载配置集合
    public synchronized static Map reloadApplicationConfiguration(){

        if (lastLoadApplicationConfigurationTime + ReloadApplicationConfigurationIntervalTime*1000 > System.currentTimeMillis()) {
            log.warn("调用载入applicationConfiguration配置过于频繁，已超过设置间隔时间："+ReloadApplicationConfigurationIntervalTime + "currentTimeMillis："+System.currentTimeMillis());
            throw new RuntimeException("调用载入applicationConfiguration配置过于频繁");
        }

        if (hashtable != null) {
            hashtable.clear();

            if (applicationConfigurationDao != null) {
                List<ApplicationConfiguration> applicationConfigurationList = applicationConfigurationDao.selectList(null);
                hashtable = new Hashtable();
                applicationConfigurationList.forEach(i->{
                    hashtable.put(i.getKeyAC(), i.getValueAC());
                });
            }else{
                WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
                Object obj = wac.getBean(ApplicationConfigurationDao.class);
                if (obj != null) {
                    applicationConfigurationDao = (ApplicationConfigurationDao) obj;
                    List<ApplicationConfiguration> applicationConfigurationList = applicationConfigurationDao.selectList(null);
                    hashtable = new Hashtable();
                    applicationConfigurationList.forEach(i->{
                        hashtable.put(i.getKeyAC(), i.getValueAC());
                    });

                }else{
                    throw new RuntimeException("初始化异常：没有拿到实例化的applicationConfigurationDao对象" + ApplicationConfigurationSingletonFactory.class.getCanonicalName());
                }

            }
        }else{
            log.warn("在重新载入应用程序配置之前没有使用getInstance()：不推荐这样用。");
            log.warn("尝试调用getInstance载入配置。。。");
            Map result = ApplicationConfigurationSingletonFactory.getInstance();
            lastLoadApplicationConfigurationTime = System.currentTimeMillis();
            return result;

        }
        lastLoadApplicationConfigurationTime = System.currentTimeMillis();
        return hashtable;
    }

//    读取配置项（从单例的配置集合中） - 字符串
    public static String getValueOfConfiguration(String key) {
        Object temp = hashtable.get(key);
        if (temp != null) {
            return temp.toString();
        }else{
            log.error("没有找到配置项："+key);
        }
        return null;
    }

}
